package note_002;

import exception.IllegalAgeException;
import exception.Person;
import exception.ThrowsDemo02;

import java.awt.*;
import java.io.FileOutputStream;
import java.io.IOException;
/**
 * 异常--------------------------------------------------异常的抛出
 */
public class day06 {
    public static void main(String[] args) {
        /**
         * java异常处理机制中的try-catch
         * 语法:
         * try{
         *     可能出现异常的代码片段
         * }catch(XXXException e){
         *     try中出现XXXException后的处理手段.
         * }
         *
         * try语句块:用来括上可能出现异常的代码片段.try语句块不能独立存在，后面必须跟
         * catch语句块或finally语句块.
         *
         * catch:语句块用来指定捕获try中出现的某异常并进行处理.
         */
//        System.out.println("程序开始啦。。。");
//
//        try {
////            String str = null;
////            String str = "";
//            String str = "a";
//            System.out.println(str.length());//当前语句出现错误，不在继续往下执行,直接跳到 catch().
//            System.out.println(str.charAt(0));//StringIndexOutOfBoundsException下标越界异常
//            System.out.println(Integer.parseInt(str));//NumberFormatException
//            System.out.println("不要过来啊!!!");
//            /*
//                try语句块中当某句代码出现了异常，则之后所有的代码均不执行.
//             */
////        } catch (NullPointerException e) {// NullPointerException
////            System.out.println("出现空指针异常并解决了!!!");
////        }catch (StringIndexOutOfBoundsException e){
////            System.out.println("出现下标越界异常并解决了!!!");
////        }
//            /*
//            可以使用多个catch分别捕获不同异常(如上面的catch操作)。也可以使用一个catch来捕获
//            多个异常。区别在于:多个catch分别捕获是因为不同异常处理方式不同。而用同一个catch捕获
//            多个异常是因为处理方式相同。
//         */
////        }catch (NullPointerException | StringIndexOutOfBoundsException e){
////                //在最后一个catch处捕获Exception可以防止因未处理的异常导致程序中断.
////
//        }catch (Exception e){
//            System.out.println("就是出了个错!");
//        }
//        /*
//            当JVM执行程序时出现了某种异常时，它便会实例化一个该异常的实例，并将程序执行过程设置到
//            其中，然后将该异常抛出等待处理，若当前方法没有异常处理机制，该异常便会自动抛出到当前方
//            法外，有调用当前方法的代码片段处理。如果最终异常抛给了JVM便会被杀掉，导致程序中断。
//         */
//        System.out.println("程序结束了...");

        /**
         * finally块是异常处理机制中的最后一个块，它可以保证程序只要执行到try语句块中，无论是否出现异常，
         * finally块中的代码都必须执行。
         *
         * finally可以直接跟在try之后或者最后一个catch之后.
         *
         * finally中通常是将释放资源这类操作放在这里，比如IO操作后的流关闭.
         */
        System.out.println("程序开始了...");

        try {
            String str = "null";

            System.out.println(str.length());
            System.out.println("无错！");
            return;   //执行完finally,执行结束
        } catch (Exception e) {
            System.out.println("出错！");
        } finally {
            System.out.println("finally中的代码执行结束了！");
        }

        System.out.println("程序结束了.....");

        /**
         * IO操作中的异常处理
         */
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("fob.txt");
            fos.write(1);
            System.out.println("你好！");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(fos!=null) {
                    fos.close();
                    System.out.println("执行结束!");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        /**
         * 请分别说明:final,finally,finalize
         * finalize:
         * finalize是一个方法，被定义在Object中，意味着所以的类都是该方法，此方法是一个
         * 对象生命周期的最后一个方法，当一个对象即将被GC释放前，GC会调用该方法，当方法
         * 执行完毕后该对象被释放。
         * 注意:
         *      若重写此方法，不能有耗时的操作，否则会影响GC的工作.
         */
//        public static void main(String[] args) {
//            System.out.println(
//                    line("0")+","+line(null)+","+line("")
//            );
//            //?,?,?
//        }
//        public static final int line(String len){
//            try {
//                return len.charAt(0)-'0';
//            } catch (NullPointerException e) {
//                return 1;
//            }catch (Exception e){
//                return 2;
//            }finally {
//                return 3;
//            }
//        }
        /**
         * JDK7之后，推出了一个新的特性:自动关闭
         * 使得我们在异常处理机制中简化了对IO的关闭操作
         * 语法:
         * try(
         *      这里初始化会在finally中调用close方法关闭的类.
         * ){
         *      ......
         * }(XXXException e){
         *     ......
         * }
         *
         * 该特性 是编译器认可的，并非虚拟机。编译器将源代码编译为close文件后改为在finally中进行close.
         */
//        try (
//                /*
//                    Java中所有得流都是实现了AutoCloseable接口，声明在这里的变量最终会被编译器
//                    改为在finally中调用其close方法关闭，相当于改为FinallyDemo2案例的样子.
//                 */
//                FileOutputStream fos = new FileOutputStream("bos.dat");
//        ){
//            String line = "";//只有实现了AutoCloseable接口的类才能在这里定义.
//            fos.write(2);
////            fos.close();//在()里书写了可以调用close方法的,可以不写
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

/**
 * 子类 重写超类含有throws声明异常抛出的方法时对throws的重写规则.
 */


//        public void dosome()throws IOException, AWTException { }
//    }
//    class SubClass extends ThrowsDemo02 {

//        /** 常规抛出异常 */
////    public void dosome()throws IOException, AWTException{}
//        /** 允许仅抛出超类方法抛出异常的部分异常 */
////    public void dosome()throws IOException{}
//        /** 允许不在抛出任何异常 */
////    public void dosome(){}
//        /** 允许抛出超类方法抛出异常的子类型异常 */
////    public void dosome()throws FileNotFoundException{}
//    /*
//       FileNotFoundException extends IOException ---- 继承,
//     */
//        /** RuntimeException(这个除外) 非检测异常*/
//        public void dosome()throws RuntimeException{}
//        /** 不允许抛出额外异常(超类方法没有抛出的且没有继承关系的) */
////    public void dosome()throws SQLException{}
//        //------------------------------------------没有继承抛出异常的类
//        /** 不允许抛出超类方法抛出异常的超类型异常 */
//    /*
//        IOException extends Exception ----------被继承, 不能比抛出异常的类大.
//     */
////    public void dosome()throws Exception{}


        /**
         * 异常常见的方法
         *
         * 输出异常堆栈信息:e.printStackTrace();---//获取错误信息(常用于记录和提示给用户使用)
         *
         */
//        System.out.println("程序开始啦...");
//
//        try {
//            //NumberFormatException:
//            String str ="a";
//            System.out.println(Integer.parseInt(str));
//        } catch (NumberFormatException e) {
//            //输出异常堆栈信息
//            e.printStackTrace();
//            //获取错误信息(常用于记录和提示给用户使用)
//            System.out.println(e.getMessage());
//        }
//        System.out.println("程序结束了...");

        /**
         * 年龄不合法异常
         *
         * 自定义异常常用于那些满足语法但是不满足业务场景时自行结合具体情况定义的异常类型。
         * 自定义异常要完成以下工作:
         * 1.:类名要见明知意
         * 2.:需要继承自Exception(直接或间接继承)
         * 3.:提供所有种类的构造方法.
         *
         * IllegalAgeException自创异常类
         *  */

        /**
         * 使用当前类测试异常的抛出
         */

//        private int age;
//
//        public int getAge() {
//            return age;
//        }
//
//        public void setAge(int age) throws IllegalAgeException {//但不合逻辑时，主动抛出异常。
//            if(age<0 || age>100){
//                /*只有RuntimeException的抛出不是必须写throws声明异常的抛出*/
////            throw new RuntimeException("年龄不合法!");
//                throw new IllegalAgeException("年龄不合法!");
//
//                /*当一个方法使用throw抛出异常时就应当在当前方法上使用throw声明该异常的抛出*/
//                //当调用此方法异常抛出时会提示你，需要捕获，可能出现的异常
//            /*
//            当调用一个含有throw声明异常抛出的方法时，编译器要求必须处理这个异常，否则编译不通过
//            处理方式有两种:
//            1.:使用try-catch捕获该异常
//            2.:在当前方法上继续使用throw声明该异常的抛出
//                具有选取那种要结合实际情况的责任制问题而定.
//         */
////            throw new Exception("年龄不合法!");//
//            }
//            this.age = age;
//        }

        /**
         *
         * throw关键字,用来主动对外抛出一个异常
         * 通常下列情况我们会主动对外抛出一个异常:
         *
         * 1.:当前代码片段出现了一个异常,但是该异常不应该被当前代码片段解决时可以对外抛出.这是责任制问题.
         *
         * 2.:当前代码出现了满足语法但是不满足业务场景时,可以主动对外抛出异常告知不应该这样做.
         *
         */
//        Person ps = new Person();
//        /*
//            当调用一个含有throw声明异常抛出的方法时，编译器要求必须处理这个异常，否则编译不通过
//            处理方式有两种:
//            1.:使用try-catch捕获该异常(Surround with try-catch)
//            2.:在当前方法上继续使用throw声明该异常的抛出
//                具有选取那种要结合实际情况的责任制问题而定.
//         */
//        try {
//            ps.setAge(1000);//满足语法,但是不满足业务.
//        } catch (IllegalAgeException e) {
//            e.printStackTrace();
//        }
//        System.out.println(ps.getAge());
//        /*
//            main 上写 throes 会被虚拟机 dikiu
//         */

        /** socket -----------------------------------------------------------------*/







    }
}
